/*
 *
 *  Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *
 *  Author : Raúl Román López <rroman@gsyc.es>
 *
 */

package com.LibreGeoSocial.App.OMF;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;

import android.util.Log;


  
/**  
 *     
 * @author   
 */  
public class Copiagenda {   
           
    /**  
     * URL del servidor https que recibe la petici�n de login  
     */  
    public static final String  TargetURLLogin = "https://copiagenda.movistar.es/cp/ps/Main/login/Agenda";   
    
    /**  
     * URL del servidor https que recibe la petici�n de reautenticaci�n 
     */
    public static final String  TargetURLAutthenticate = "https://copiagenda.movistar.es/cp/ps/Main/login/Authenticate";   
    
    /**  
     * URL del servidor https que recibe la petici�n de datos 
     */
    public static final String  TargetURLDatos = "https://copiagenda.movistar.es/cp/ps/PSPab/preferences/ExportContacts?d=movistar.es&c=yes";   
    
	private String login = null;
	private String pwd = null;
	private String urlRedireccion = null;
	private String sCookie = null;
	private String password;
	private String sReautenticacionT = null;
	private List<String> contactList = null;
	private String message = "Ok";
	
	private static TrustManager[] trustManagers;
	
	public Copiagenda() {
		super();
	}
         
	public String getMessage(){
		return message;
	}
	
    /**
     * @param login
     * @param pwd
     */
    public List<String> RetrieveContacts (String login, String pwd) {
    	this.login = login;
		this.pwd = pwd;
    	
		if(Login()) {
			if(Redireccion()) {
				if(Reautenticacion()) {
					if(Datos()) {
						message = "OK";
			    	}
				}
	    	}
    		
    	}
    		
		/*
    	if(! Login() && ! Redireccion() && ! Reautenticacion() && ! Datos()) {
    		System.out.println("Username or password not valid");  
    		return this.contactList ;
    	}
    	*/
		
    	// devuelve la lista de contactos
    	return this.contactList ;
    }
   
    public boolean Login () {
    	
    	Copiagenda.allowAllSSL();
    	
    	URL url;
		HttpsURLConnection urlConn;
  
        boolean ret = true;
        int	status = 0; 
        try {
			url = new URL(Copiagenda.TargetURLLogin);
			
			urlConn = (HttpsURLConnection) url.openConnection();
			
			// set Post method
	        urlConn.setDoOutput (true);
	        
	        // setting headers
	        urlConn.setRequestMethod("POST");
	        urlConn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");       
	        urlConn.setRequestProperty("Accept-Encoding", "gzip, deflate");
	        urlConn.setRequestProperty("Host", "copiagenda.movistar.es"); 
	        urlConn.setRequestProperty("Accept", "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"); 
            urlConn.setRequestProperty("Connection", "Keep-Alive");
            urlConn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727)");
            
	        // making content
	        String data = "TM_ACTION=" + "LOGIN" + 
	        				"&TM_LOGIN="+ this.login +
	        				"&TM_PASSWORD=" + this.pwd;
	        
	        // writing content
			OutputStreamWriter out = new OutputStreamWriter(urlConn.getOutputStream());
			out.write (data);
			out.flush();
	        
			// getting response
			
			BufferedReader in = new BufferedReader(
					new InputStreamReader(
							urlConn.getInputStream()));
			
			status = urlConn.getResponseCode();
			
            if (status == HttpsURLConnection.HTTP_MOVED_TEMP) {   

            	List<String> headers = urlConn.getHeaderFields().get("set-cookie");
                String sCookie = null;
                // extrae las cookies necesarias para la redirecci�n
                for (int i = 0; i < headers.size(); i++) {
                	if (headers.get(i).contains("s=")) {
                		sCookie = headers.get(i).substring(0, headers.get(i).indexOf(";") + 2);
                	}
                	if (headers.get(i).contains("skf=")) {
                		sCookie += headers.get(i).substring(0, headers.get(i).indexOf(";"));
                	}
                }
                
                this.sCookie = sCookie;
                // extrae la url de redirecci�n
                this.urlRedireccion = urlConn.getHeaderField("Location");
                
            } else {
            	message = "login: " + Integer.toString(status);
            	ret = false;
            }
			
			out.close();
			in.close();
			
		} catch (MalformedURLException e) {
			message = "login: " + e.toString();
			ret = false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			message = "login: " + e.toString();
			ret = false;
		}
        
        // devuelve true si login y password son correctos
        return ret;
    	
    }

    public boolean Redireccion() {
    	
    	Copiagenda.allowAllSSL();
    	
    	URL url;
		HttpsURLConnection urlConn;
  
        boolean ret = true;
        int	status = 0; 
        try {
			url = new URL(this.urlRedireccion);
			
			urlConn = (HttpsURLConnection) url.openConnection();
			
			// set Post method
	        urlConn.setDoOutput (false);
	        
	        // setting headers
	        urlConn.setRequestMethod("GET");
	        urlConn.setRequestProperty("Accept-Encoding", "gzip, deflate");
	        urlConn.setRequestProperty("Host", "copiagenda.movistar.es"); 
	        urlConn.setRequestProperty("Accept", "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"); 
            urlConn.setRequestProperty("Connection", "Keep-Alive");
            urlConn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727)");
            urlConn.setRequestProperty("Cookie", this.sCookie);
            
	        	        
			// getting response
			
			BufferedReader in = new BufferedReader(
					new InputStreamReader(
							urlConn.getInputStream()));
			
			status = urlConn.getResponseCode();
			
            if (status == HttpsURLConnection.HTTP_OK) {   
            	String respuesta = "";
            	String line;
            	while ((line = in.readLine())!=null){
					respuesta += line;
				}
                Integer iInicioPw = respuesta.indexOf("name=\"password\" value=");
                iInicioPw = respuesta.indexOf("value=",iInicioPw)+6;
                Integer iFinPw = respuesta.indexOf(">",iInicioPw);
                // recupera el password para la posterior reautenticaci�n
                this.password= respuesta.substring(iInicioPw, iFinPw);
                
            } else {
            	message = "redireccion: " + Integer.toString(status);
            	ret = false;
            }
			
			in.close();
			
		} catch (MalformedURLException e) {
			message = "redireccion: " + e.toString();
			ret = false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			message = "redireccion: " + e.toString();
			ret = false;
		}
        
        // devuelve true si login y password son correctos
        return ret;
    	
	}
    
    
    public boolean Reautenticacion () {
    	
    	Copiagenda.allowAllSSL();
    	
    	URL url;
		HttpsURLConnection urlConn;
  
        boolean ret = true;
        int	status = 0; 
        try {
			url = new URL(Copiagenda.TargetURLAutthenticate);
			
			urlConn = (HttpsURLConnection) url.openConnection();
			
			// set Post method
	        urlConn.setDoOutput (true);
	        
	        // setting headers
	        urlConn.setRequestMethod("POST");
	        urlConn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");       
	        urlConn.setRequestProperty("Accept-Encoding", "gzip, deflate");
	        urlConn.setRequestProperty("Host", "copiagenda.movistar.es"); 
	        urlConn.setRequestProperty("Referer", this.urlRedireccion);
	        urlConn.setRequestProperty("Accept-Language", "es");
	        urlConn.setRequestProperty("Cache-Control", "no-cache");
	        urlConn.setRequestProperty("Accept", "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"); 
            urlConn.setRequestProperty("Connection", "Keep-Alive");
            urlConn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727)");
            urlConn.setRequestProperty("Cookie", this.sCookie);
            
            // making content
	        String data = "password=" + this.password + 
	        				"&u="+ this.login +
	        				"&d=" + "movistar.es";
	        
	        // writing content
			OutputStreamWriter out = new OutputStreamWriter(urlConn.getOutputStream());
			out.write (data);
			out.flush();
			// getting response
			
			BufferedReader in = new BufferedReader(
					new InputStreamReader(
							urlConn.getInputStream()));
			
			status = urlConn.getResponseCode();
			
            if (status == HttpsURLConnection.HTTP_OK) {   
            	String respuesta = "";
            	String line;
            	while ((line = in.readLine())!=null){
					respuesta += line;
				}
                Integer iInicioT = respuesta.indexOf("&t=")+3;
                Integer iFinT = respuesta.indexOf("\"",iInicioT);
                // recupera el password para la posterior reautenticaci�n
                this.sReautenticacionT = respuesta.substring(iInicioT, iFinT);
                //devuelve estado 200=OK pero con errores
                if((iFinT - iInicioT) > 6) ret = false;
            } else {
            	message = "Reautenticacion: " + Integer.toString(status);
            	ret = false;
            }
			
			in.close();
			
		} catch (MalformedURLException e) {
			message = "Reautenticacion: " + e.toString();
			ret = false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			message = "Reautenticacion: " + e.toString();
			ret = false;
		}
        
        // devuelve true si login y password son correctos
        return ret;
    	
    }
    
    public boolean Datos () {
    	
    	Copiagenda.allowAllSSL();
    	
    	URL url;
		HttpsURLConnection urlConn;
  
        boolean ret = true;
        int	status = 0; 
        String sUrl = Copiagenda.TargetURLDatos + "&u=" + this.login + "&t=" + this.sReautenticacionT;
        try {
			url = new URL(sUrl);
			
			urlConn = (HttpsURLConnection) url.openConnection();
			
			// set Post method
	        urlConn.setDoOutput (true);
	        
	        // setting headers
	        urlConn.setRequestMethod("POST");
	        urlConn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");       
	        urlConn.setRequestProperty("Accept-Encoding", "gzip, deflate");
	        urlConn.setRequestProperty("Host", "copiagenda.movistar.es"); 
	        urlConn.setRequestProperty("Referer", this.urlRedireccion);
	        urlConn.setRequestProperty("Accept-Language", "es");
	        urlConn.setRequestProperty("Cache-Control", "no-cache");
	        urlConn.setRequestProperty("Accept", "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"); 
            urlConn.setRequestProperty("Connection", "Keep-Alive");
            urlConn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727)");
            urlConn.setRequestProperty("Cookie", this.sCookie);
            
            // making content
	        String data = "FileFormat=" + "TEXT" + 
	        				"&charset="+ "8859_1" +
	        				"&delimiter=" + "TAB";
	        
	        
	        // writing content
			OutputStreamWriter out = new OutputStreamWriter(urlConn.getOutputStream());
			out.write (data);
			out.flush();
			// getting response
			
			BufferedReader in = new BufferedReader(
					new InputStreamReader(
							urlConn.getInputStream()));
			
			status = urlConn.getResponseCode();
			
            if (status == HttpsURLConnection.HTTP_OK) {   
            	String respuesta = "";
            	String line;
            	while ((line = in.readLine())!=null){
					respuesta += line +"\n";
				}
            	String sListaContactos [] = respuesta.split("\n\n");
                String lista [] =sListaContactos[0].split("\n");
                
            	List<String> Contactos = new ArrayList<String>(); 
                for (int i = 0; i < lista.length; i++) {
                	try {
                		if(i!=0)
                			Contactos.add(lista[i]);		                		
                	}
                	catch(Exception e){
                		//System.out.println("Failed to read the contact list");
                	}
                }
                
               // devuelve un array con los contactos
               this.contactList = Contactos;
               //devuelve estado 200=OK pero con errores
               if (lista.length < 2) {
            	   message = "Datos: There are no contacts";
            	   ret = false;
               }
            } else {
            	message = "Datos: " + Integer.toString(status);
            	ret = false;
            }
			
			in.close();
			
		} catch (MalformedURLException e) {
			message = "Datos: " + e.toString();
			ret = false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			message = "Datos: " + e.toString();
			ret = false;
		}
        
        // devuelve true si login y password son correctos
        return ret;
    	
    }
    
    public List<String> SearchByName(String name,List<String> contactList) {
    	List<String> contact = new ArrayList<String>();
    	
    	if (contactList != null && contactList.size()> 0) {
    		
    		for (int i = 0; i < contactList.size(); i++) {
            	try {
            		
            		String sContacto [] = contactList.get(i).replaceAll("\"", "").split(",");
            		if(sContacto[3].equalsIgnoreCase(name)) {
            			contact.add(contactList.get(i));
            		}
            	}
            	catch(Exception e){
            		message = "Failed to read the contact list";
            	}
            }
    	} else
    		contact = null;
    	
    	return contact;
    }
    
	public static void allowAllSSL(){
		javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){

			public boolean verify(String hostname, SSLSession session) {
				// TODO Auto-generated method stub
				return true;
			}
			
		});
		
		javax.net.ssl.SSLContext context = null;
		
		if(trustManagers==null){
			trustManagers = new javax.net.ssl.TrustManager[]{new _FakeX509TrustManager()};
		}
		
		try{
			context = javax.net.ssl.SSLContext.getInstance("TLS");
			context.init(null, trustManagers, new SecureRandom());
			
		}catch(NoSuchAlgorithmException e){
			Log.e("allowAllSSL", e.toString());
		}catch(KeyManagementException e){
			Log.e("allowAllSSL", e.toString());
		}
		
		javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
		
	}
	
	public static class _FakeX509TrustManager implements javax.net.ssl.X509TrustManager{
		
		private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};
		
		public void checkClientTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
			// TODO Auto-generated method stub
			
		}

		public void checkServerTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
			// TODO Auto-generated method stub
			
		}
		
		public boolean isClientTrusted(X509Certificate[] chain){
			return true;
		}
		
		public boolean isServerTrusted(X509Certificate[] chain){
			return true;
		}
		
		public X509Certificate[] getAcceptedIssuers() {
			// TODO Auto-generated method stub
			return _AcceptedIssuers;
		}
		
	}
    
} 
